#include "user_uart.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/uart.h"
#include "esp_log.h"
#include "string.h"
#include "user_include.h"


#define EX_UART_NUM UART_NUM_1
#define PATTERN_CHR_NUM    (3)         /*!< Set the number of consecutive and identical characters received by receiver which defines a UART pattern*/

#define RX_BUF_SIZE 1024

#define UART_TX_PIN 16
#define UART_RX_PIN 17

const char *TAG = "UART";

void user_uart_init(void) {
    const uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_DEFAULT,
    };
    // We won't use a buffer for sending data.
    uart_driver_install(UART_NUM_1, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
    uart_param_config(UART_NUM_1, &uart_config);
    uart_set_pin(UART_NUM_1, UART_TX_PIN, UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}

int sendData(uint8_t *data, uint32_t len)
{
    const int txBytes = uart_write_bytes(UART_NUM_1, data, len);
    return txBytes;
}

void hexdump(uint8_t *data, uint32_t len)
{
    uint32_t pkt = len / 16;
    uint8_t offset = len % 16;

    for(uint32_t i= 0; i < pkt; i++)
    {
    	for(uint8_t j = 0; j < 16; j++)
	{
	    printf("%02x ",data[i * 16 + j]);
	}
	printf("\r\n");
    }
    for(uint8_t j = 0; j < offset; j++)
    {
	printf("%02x ",data[pkt * 16 + j]);
    }
    printf("\r\n");
}

void tx_task(void *arg)
{
    
    printf("%s %d start\r\n",__func__, __LINE__);
    while (1) {   
	if(uart_send_flag.head != uart_send_flag.tail)
	{
	    sendData(uart_send_flag.data[uart_send_flag.head], uart_send_flag.len[uart_send_flag.head]);
    	    printf("%s %d head:%d\r\n",__func__, __LINE__, uart_send_flag.head);
	    hexdump(uart_send_flag.data[uart_send_flag.head], uart_send_flag.len[uart_send_flag.head]);		
	    uart_send_flag.head = (uart_send_flag.head + 1) %UART_SEND_MAX;    
	}
       	vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}

void rx_task(void *arg)
{
    printf("%s %d start\r\n",__func__, __LINE__);
    uint8_t* data = (uint8_t*) malloc(RX_BUF_SIZE+1);
    while (1) {
        const int rxBytes = uart_read_bytes(UART_NUM_1, data, RX_BUF_SIZE, 50 / portTICK_PERIOD_MS);
        if (rxBytes > 0) {
            data[rxBytes] = 0;
            printf("%s %d tail:%d\r\n",__func__, __LINE__, uart_recv_flag.tail);
	    uart_recv_flag.len[uart_recv_flag.tail] = rxBytes;
	    strcpy((char *)uart_recv_flag.data[uart_recv_flag.tail], (char *)data);
	    hexdump(uart_recv_flag.data[uart_recv_flag.tail], uart_recv_flag.len[uart_recv_flag.tail]);
	    uart_recv_flag.tail = (uart_recv_flag.tail + 1) % UART_RECV_MAX;
        }
    }
    free(data);
}

void uart_task(void *arg)
{
    user_uart_init();
    xTaskCreate(rx_task, "uart_rx_task", 1024*2, NULL, configMAX_PRIORITIES, NULL);
    xTaskCreate(tx_task, "uart_tx_task", 1024*2, NULL, configMAX_PRIORITIES-1, NULL);
}

